var http = require("http");

http
  .createServer(function (request, response) {
    // 发送 HTTP 头部
    // HTTP 状态值: 200 : OK
    // 内容类型: text/plain
    response.writeHead(200, { "Content-Type": "text/plain" });

    // 发送响应数据 "Hello World"
    response.end("Hello World\n");
  })
  .listen(8888);

//------
var x = 10;
var y = 20;
x + y;
var sum = x + y;
console.log(sum);

//------
var fs = require("fs");

var data = fs.readFileSync("../package.json");

console.log(data.toString());
console.log("程序执行结束!");

// fs.readFile('package.json', function (err, data) {
//     if (err) return console.error(err);
//     console.log(data.toString());
// });

console.log("程序执行结束!");

//----------
// 引入 events 模块
var events = require("events");
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();

// 创建事件处理程序
var connectHandler = function connected() {
  console.log("连接成功。");

  // 触发 data_received 事件
  eventEmitter.emit("data_received");
};

// 绑定 connection 事件处理程序
eventEmitter.on("connection", connectHandler);

// 使用匿名函数绑定 data_received 事件
eventEmitter.on("data_received", function () {
  console.log("数据接收成功。");
});

// 触发 connection 事件
eventEmitter.emit("connection");

console.log("程序执行完毕。");

//----------
//event.js 文件
var EventEmitter = require("events").EventEmitter;
var event = new EventEmitter();
event.on("some_event", function () {
  console.log("some_event 事件触发");
});
setTimeout(function () {
  event.emit("some_event");
}, 1000);
//----------
//event.js 文件
var events = require("events");
var emitter = new events.EventEmitter();
emitter.on("someEvent", function (arg1, arg2) {
  console.log("listener1", arg1, arg2);
});
emitter.on("someEvent", function (arg1, arg2) {
  console.log("listener2", arg1, arg2);
});
emitter.emit("someEvent", "arg1 参数", "arg2 参数");

//----------
var events = require("events");
var eventEmitter = new events.EventEmitter();

// 监听器 #1
var listener1 = function listener1() {
  console.log("监听器 listener1 执行。");
};

// 监听器 #2
var listener2 = function listener2() {
  console.log("监听器 listener2 执行。");
};

// 绑定 connection 事件，处理函数为 listener1
eventEmitter.addListener("connection", listener1);

// 绑定 connection 事件，处理函数为 listener2
eventEmitter.on("connection", listener2);

var eventListeners = eventEmitter.listenerCount("connection");
console.log(eventListeners + " 个监听器监听连接事件。");

// 处理 connection 事件
eventEmitter.emit("connection");

// 移除监绑定的 listener1 函数
eventEmitter.removeListener("connection", listener1);
console.log("listener1 不再受监听。");

// 触发连接事件
eventEmitter.emit("connection");

eventListeners = eventEmitter.listenerCount("connection");
console.log(eventListeners + " 个监听器监听连接事件。");

console.log("程序执行完毕。");

//----------
// emitter.emit('error');

//----------
var buf = Buffer.from("runoob", "ascii");

// 输出 72756e6f6f62
console.log(buf.toString("hex"));

// 输出 cnVub29i
console.log(buf.toString("base64"));

//----------
// 创建一个长度为 10、且用 0 填充的 Buffer。
var buf1 = Buffer.alloc(10);

// 创建一个长度为 10、且用 0x1 填充的 Buffer。
var buf2 = Buffer.alloc(10, 1);

// 创建一个长度为 10、且未初始化的 Buffer。
// 这个方法比调用 Buffer.alloc() 更快，
// 但返回的 Buffer 实例可能包含旧数据，
// 因此需要使用 fill() 或 write() 重写。
const buf3 = Buffer.allocUnsafe(10);

// 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);

// 创建一个包含 UTF-8 字节 [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。
const buf5 = Buffer.from("tést");

// 创建一个包含 Latin-1 字节 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
const buf6 = Buffer.from("tést", "latin1");

//----------
buf = Buffer.alloc(256);
len = buf.write("www.runoob.com");

console.log("写入字节数 : " + len);

//----------
buf = Buffer.alloc(26);
for (var i = 0; i < 26; i++) {
  buf[i] = i + 97;
}

console.log(buf.toString("ascii")); // 输出: abcdefghijklmnopqrstuvwxyz
console.log(buf.toString("ascii", 0, 5)); //使用 'ascii' 编码, 并输出: abcde
console.log(buf.toString("utf8", 0, 5)); // 使用 'utf8' 编码, 并输出: abcde
console.log(buf.toString(undefined, 0, 5)); // 使用默认的 'utf8' 编码, 并输出: abcde

//----------
buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);

// 输出: {"type":"Buffer","data":[1,2,3,4,5]}
console.log(json);

const copy = JSON.parse(json, (key, value) => {
  return value && value.type === "Buffer" ? Buffer.from(value.data) : value;
});

// 输出: <Buffer 01 02 03 04 05>
console.log(copy);

//----------
var buffer1 = Buffer.from("菜鸟教程");
var buffer2 = Buffer.from("www.runoob.com");
var buffer3 = Buffer.concat([buffer1, buffer2]);
console.log("buffer3 内容: " + buffer3.toString());

//----------
var buffer1 = Buffer.from("D");
var buffer2 = Buffer.from("CD");
var result = buffer1.compare(buffer2);

if (result < 0) {
  console.log(buffer1 + " 在 " + buffer2 + "之前");
} else if (result == 0) {
  console.log(buffer1 + " 与 " + buffer2 + "相同");
} else {
  console.log(buffer1 + " 在 " + buffer2 + "之后");
}
//----------
buf1 = Buffer.from("abcdefghijkl");
buf2 = Buffer.from("RUNOOB");

//将 buf2 插入到 buf1 指定位置上
buf2.copy(buf1, 2);

console.log(buf1.toString());

//----------
var buffer1 = Buffer.from("runoob");
// 剪切缓冲区
var buffer2 = buffer1.slice(0, 2);
console.log("buffer2 content: " + buffer2.toString());

//----------
var buffer = Buffer.from("www.runoob.com");
//  缓冲区长度
console.log("buffer length: " + buffer.length);

//----------
var fs = require("fs");
var data = "";

// 创建可读流
var readerStream = fs.createReadStream("package.json");

// 设置编码为 utf8。
readerStream.setEncoding("UTF8");

// 处理流事件 --> data, end, and error
readerStream.on("data", function (chunk) {
  data += chunk;
});

readerStream.on("end", function () {
  console.log(data);
});

readerStream.on("error", function (err) {
  console.log(err.stack);
});

console.log("程序执行完毕");

//---------

var fs = require("fs");
var data = "菜鸟教程官网地址：www.runoob.com";

// 创建一个可以写入的流，写入到文件 output.txt 中
var writerStream = fs.createWriteStream("output.txt");

// 使用 utf8 编码写入数据
writerStream.write(data, "UTF8");

// 标记文件末尾
writerStream.end();

// 处理流事件 --> finish、error
writerStream.on("finish", function () {
  console.log("写入完成。");
});

writerStream.on("error", function (err) {
  console.log(err.stack);
});

console.log("程序执行完毕");

//-----------

var fs = require("fs");

// 创建一个可读流
var readerStream = fs.createReadStream("input.txt");

// 创建一个可写流
var writerStream = fs.createWriteStream("output.txt");

// 管道读写操作
// 读取 input.txt 文件内容，并将内容写入到 output.txt 文件中
readerStream.pipe(writerStream);

//----------
var fs = require("fs");
var zlib = require("zlib");

// 压缩 input.txt 文件为 input.txt.gz
fs.createReadStream("input.txt")
  .pipe(zlib.createGzip())
  .pipe(fs.createWriteStream("input.txt.gz"));

console.log("文件压缩完成。");

console.log("程序执行完毕");
//----------

// 解压 input.txt.gz 文件为 input2.txt///???????????有问题
// fs.createReadStream('input.txt.gz')
//   .pipe(zlib.createGunzip())
//   .pipe(fs.createWriteStream('input 2.txt'));

console.log("文件解压没完成。！！！！");

//----------

function say(word) {
  console.log(word);
}

function execute(someFunction, value) {
  someFunction(value);
}

execute(say, "Hello");

execute(function (word) {
  console.log(word);
}, "Hello");

http
  .createServer(function (request, response) {
    response.writeHead(200, { "Content-Type": "text/plain" });
    response.write("Hello World 8889");
    response.end();
  })
  .listen(8889);

//----------
// 结论：闭包找到的是同一地址中父级函数中对应变量最终的值
// 最终秘诀就这一句话，每个例子请自行带入这个结论！！！！！！！！！！！！！
function fn() {
  var arr = [];
  for (var i = 0; i < 5; i++) {
    arr[i] = (function (i) {
      return function () {
        return i;
      };
    })(i);
  }
  return arr;
}
var list = fn();
console.log(list);
for (var i = 0, len = list.length; i < len; i++) {
  console.log(list[i]());
} //0 1 2 3 4
//----------

console.log(__filename);

//----------
function printHello() {
  console.log("Hello, World printHello!");
}
// 两秒后执行以上函数
var t = setTimeout(printHello, 2000);
// 清除定时器
// clearTimeout(t);
// 两秒后执行以上函数
// setInterval(printHello, 2000);
//----------

console.log("byvoid%diovyb", 1991);
console.trace();
console.info("console程序开始执行：");

var counter = 10;
console.log("计数: %d", counter);

console.time("获取数据");
//
// 执行一些代码
//
console.timeEnd("获取数据");

console.info("console程序执行完毕。");

//----------
process.on("exit", function (code) {
  // 以下代码永远不会执行
  setTimeout(function () {
    console.log("该代码不会执行");
  }, 0);

  console.log("退出码为:", code);
});
console.log("程序执行结束");

//----------
// 输出到终端
process.stdout.write("Hello World!" + "\n");

// 通过参数读取
process.argv.forEach(function (val, index, array) {
  console.log(index + ": " + val);
});

// 获取执行路径
console.log(process.execPath);

// 平台信息
console.log(process.platform);
//----------
// 输出当前目录
console.log("当前目录: " + process.cwd());

// 输出当前版本
console.log("当前版本: " + process.version);

// 输出内存使用情况
console.log(process.memoryUsage());

//----------
var util = require("util");

async function fn() {
  return "hello world";
}
const callbackFunction = util.callbackify(fn);

callbackFunction((err, ret) => {
  if (err) throw err;
  console.log(ret);
});

// function fn() {
//    return Promise.reject(null);
// }
// const callbackFunction2 = util.callbackify(fn);

// callbackFunction2((err, ret) => {
//    // 当 Promise 被以 `null` 拒绝时，它被包装为 Error 并且原始值存储在 `reason` 中。
//    err && err.hasOwnProperty('reason') && err.reason === null;  // true
//    console.log(ret);
// });

//-----------

function Base() {
  this.name = "base";
  this.base = 1991;
  this.sayHello = function () {
    console.log("Hello " + this.name);
  };
}
Base.prototype.showName = function () {
  console.log(this.name);
};
function Sub() {
  this.name = "sub";
}
util.inherits(Sub, Base);
var objBase = new Base();
objBase.showName();
objBase.sayHello();
console.log(objBase);
var objSub = new Sub();
objSub.showName();
// objSub.sayHello();
console.log(objSub);

//----------

function Person() {
  this.name = "byvoid";
  this.toString = function () {
    return this.name;
  };
}
var obj = new Person();
console.log(util.inspect(obj));
console.log(util.inspect(obj, true));

//----------
util.isArray([]);
// true
util.isArray(new Array());
// true
util.isArray({});
// false
util.isRegExp(/some regexp/);
// true
util.isRegExp(new RegExp("another regexp"));
// true
util.isRegExp({});
// false
util.isDate(new Date());
// true
util.isDate(Date());
// false (without 'new' returns a String)
util.isDate({});
// false
//https://nodejs.org/api/util.html

//----------

fs.readFile("input.txt", function (err, data) {
  if (err) {
    return console.error(err);
  }
  console.log("异步读取: " + data.toString());
});
// 同步读取
var data = fs.readFileSync("input.txt");
console.log("同步读取: " + data.toString());

console.log("程序执行完毕。");

//---------
console.log("准备打开文件！");
fs.open("input.txt", "r+", function (err, fd) {
  if (err) {
    return console.error(err);
  }
  console.log("文件打开成功！");
});

//----------
fs.stat("input.txt", function (err, stats) {
  if (err) {
    return console.error(err);
  }
  console.log(stats);
  console.log("读取文件信息成功！");

  // 检测文件类型
  console.log("是否为文件(isFile) ? " + stats.isFile());
  console.log("是否为目录(isDirectory) ? " + stats.isDirectory());
});
//----------
fs.writeFile(
  "input.txt",
  "我是通 过fs.writeFile 写入文件的内容",
  function (err) {
    if (err) {
      return console.error(err);
    }
    console.log("数据写入成功！");
    console.log("--------我是分割线-------------");
    console.log("读取写入的数据！");
    fs.readFile("input.txt", function (err, data) {
      if (err) {
        return console.error(err);
      }
      console.log("异步读取文件数据: " + data.toString());
    });
  }
);
//-----------

var buf = new Buffer.alloc(1024);

console.log("准备打开已存在的文件！");
fs.open("input.txt", "r+", function (err, fd) {
  if (err) {
    return console.error(err);
  }
  console.log("文件打开成功！");
  console.log("准备读取文件：");
  fs.read(fd, buf, 0, buf.length, 0, function (err, bytes) {
    if (err) {
      console.log(err);
    }
    console.log(bytes + "  字节被读取");

    // 仅输出读取的字节
    if (bytes > 0) {
      console.log(buf.slice(0, bytes).toString());
    }

    // 关闭文件
    fs.close(fd, function (err) {
      if (err) {
        console.log(err);
      }
      console.log("文件关闭成功");
    });
  });
});

//----------

buf = new Buffer.alloc(1024);

console.log("准备打开文件！");
fs.open("input.txt", "r+", function (err, fd) {
  if (err) {
    return console.error(err);
  }
  console.log("文件打开成功！");
  console.log("截取10字节内的文件内容，超出部分将被去除。");

  // 截取文件
  fs.ftruncate(fd, 10, function (err) {
    if (err) {
      console.log(err);
    }
    console.log("文件截取成功。");
    console.log("读取相同的文件");
    fs.read(fd, buf, 0, buf.length, 0, function (err, bytes) {
      if (err) {
        console.log(err);
      }

      // 仅输出读取的字节
      if (bytes > 0) {
        console.log(buf.slice(0, bytes).toString());
      }

      // 关闭文件
      fs.close(fd, function (err) {
        if (err) {
          console.log(err);
        }
        console.log("文件关闭成功！");
      });
    });
  });
});

//--------------

var http = require("http");
var url = require("url");
var util = require("util");

http
  .createServer(function (req, res) {
    res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });

    // 解析 url 参数
    var params = url.parse(req.url, true).query;
    res.write("网站名：" + params.name);
    res.write("\n");
    res.write("网站 URL：" + params.url);
    res.write("\n");

    res.end(util.inspect(url.parse(req.url, true)));
  })
  .listen(3000);

//----------
var http = require("http");
var querystring = require("querystring");
var util = require("util");

var postHTML =
  '<html><head><meta charset="utf-8"><title>菜鸟教程 Node.js 实例</title></head>' +
  "<body>" +
  '<form method="post">' +
  '网站名： <input name="name"><br>' +
  '网站 URL： <input name="url"><br>' +
  '<input type="submit">' +
  "</form>" +
  "</body></html>";

http
  .createServer(function (req, res) {
    // 定义了一个post变量，用于暂存请求体的信息
    var post = "";

    // 通过req的data事件监听函数，每当接受到请求体的数据，就累加到post变量中
    req.on("data", function (chunk) {
      post += chunk;
    });

    // 在end事件触发后，通过querystring.parse将post解析为真正的POST请求格式，然后向客户端返回。
    req.on("end", function () {
      // 解析参数
      post = querystring.parse(post);
      // 设置响应头部信息及编码
      res.writeHead(200, { "Content-Type": "text/html; charset=utf8" });

      if (post.name && post.url) {
        // 输出提交的数据
        res.write("网站名：" + post.name);
        res.write("<br>");
        res.write("网站 URL：" + post.url);
      } else {
        // 输出表单
        res.write(postHTML);
      }
      res.end();
    });
  })
  .listen(3001);

//-----------
var os = require("os");

// CPU 的字节序
console.log('endianness : ' + os.endianness());

// 操作系统名
console.log('type : ' + os.type());

// 操作系统名
console.log('platform : ' + os.platform());

// 系统内存总量
console.log('total memory : ' + os.totalmem() + " bytes.");

// 操作系统空闲内存量
console.log('free memory : ' + os.freemem() + " bytes.");

//----------
var path = require("path");

// 格式化路径
console.log('normalization : ' + path.normalize('/test/test1//2slashes/1slash/tab/..'));

// 连接路径
console.log('joint path : ' + path.join('/test', 'test1', '2slashes/1slash', 'tab', '..'));

// 转换为绝对路径
console.log('resolve : ' + path.resolve('main.js'));

// 路径中文件的后缀名
console.log('ext name : ' + path.extname('main.js'));
//----------
var net = require('net');
var server = net.createServer(function(connection) { 
   console.log('client connected');
   connection.on('end', function() {
      console.log('客户端关闭连接');
   });
   connection.write('Hello World!\r\n');
   connection.pipe(connection);
});
server.listen(8080, function() { 
  console.log('server is listening');
});
var client = net.connect({port: 8080}, function() {
  console.log('连接到服务器！');  
});
client.on('data', function(data) {
  console.log(data.toString());
  client.end();
});
client.on('end', function() { 
  console.log('断开与服务器的连接');
});

//----------
var dns = require('dns');

dns.lookup('www.github.com', function onLookup(err, address, family) {
   console.log('ip 地址:', address);
   dns.reverse(address, function (err, hostnames) {
   if (err) {
      console.log(err.stack);
   }

   console.log('反向解析 ' + address + ': ' + JSON.stringify(hostnames));
});  
});

//----------
var EventEmitter = require("events").EventEmitter;
var domain = require("domain");

var emitter1 = new EventEmitter();

// 创建域
var domain1 = domain.create();

domain1.on('error', function(err){
   console.log("domain1 处理这个错误 ("+err.message+")");
});

// 显式绑定
domain1.add(emitter1);

emitter1.on('error',function(err){
   console.log("监听器处理此错误 ("+err.message+")");
});

emitter1.emit('error',new Error('通过监听器来处理'));

emitter1.removeAllListeners('error');

emitter1.emit('error',new Error('通过 domain1 处理'));

var domain2 = domain.create();

domain2.on('error', function(err){
   console.log("domain2 处理这个错误 ("+err.message+")");
});

// 隐式绑定
domain2.run(function(){
   var emitter2 = new EventEmitter();
   emitter2.emit('error',new Error('通过 domain2 处理'));   
});


domain1.remove(emitter1);
// emitter1.emit('error', new Error('转换为异常，系统将崩溃!'));

//----------


// emitter.emit("error");

// 终端打印如下信息
console.log("Server running at http://127.0.0.1:8888/");
console.log("Server running at http://127.0.0.1:8889/");
console.log("Server running at http://localhost:3000/a?name=b&url=c.d.e");
console.log("Server running at http://localhost:3001");
console.log("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
